#include "EPSC_manager.h"

namespace wilson::coro
{
    constexpr uint64_t blk_size{ 512U };

    EPSC_manager::EPSC_manager()
        : EPSC_manager{ 2 }
    {
    }

    EPSC_manager::EPSC_manager(size_t init_cur)
        : em_init_blk{ init_cur }
    {
        for (size_t cur = 0; cur < em_init_blk; ++cur)
        {
            em_ctxs.push_back(new epoll_suspended_context[blk_size]{});
        }
    }

    EPSC_manager::~EPSC_manager() noexcept
    {
        for (auto* blk_p : em_ctxs)
            delete[] blk_p;
    }

    epoll_suspended_context* EPSC_manager::operator[](size_t fd)
    {
        ::std::shared_lock lock_outter{ em_mutex };
        size_t target_blk = fd / blk_size;
        size_t item_idx = fd % blk_size;
        if (target_blk >= em_ctxs.size())
        {
            lock_outter.unlock();
            ::std::unique_lock lock{ em_mutex };
            while (target_blk >= em_ctxs.size())
                em_ctxs.push_back(new epoll_suspended_context[blk_size]{});
            lock_outter.lock();
        }
        return &em_ctxs[target_blk][item_idx];
    }

    size_t EPSC_manager::size() const noexcept
    {
        ::std::shared_lock lock{ em_mutex };
        return em_ctxs.size() * blk_size;
    }
}
